package com.qf.service.impl;

import com.qf.entity.*;
import com.qf.mapper.RoleMapper;
import com.qf.mapper.SysUserRoleMapper;
import com.qf.util.JwtUtils;
import com.qf.mapper.UserMapper;
import com.qf.service.UserService;
import com.qf.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private RedisUtil redisUtil;
    @Value("${token.expireTime}")
    private int expireTime;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;


    @Override
    public String login(User user) {
        /**
         * 1.调用AuthenticationManager的authenticate方法,完成认证
         */
        Authentication authenticate = null;
        try {
            // 调用UserDetailServiceImpl的loadUserByUsername方法,根据用户名查询用户信息
            // 需要通过AuthenticationManager来完成调用
            authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));

        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                throw new RuntimeException("用户认证失败");
            } else {
                throw new RuntimeException(e.getMessage());
            }
        }

        /**
         * 2.如果认证成功,则创建token
         */
        Map<String,Object> claims = new HashMap<>();
        claims.put("username",user.getUsername());
        // 获取权限对象，用于提取权限数据
        Collection<? extends GrantedAuthority> authorities = authenticate.getAuthorities();
        Set<String> authoritySet = new HashSet<>();
        authorities.forEach(item -> authoritySet.add(item.getAuthority()));
        // 将权限数据放入claims,用于存入jwt
        claims.put("perms", authoritySet);

        //生成uuid
        String s = UUID.randomUUID().toString();
        String uuid = s.replace("-", "");
        // 将uuid储存到jwt的token中
        claims.put("uuid", uuid);
        // 创建token
        String token = jwtUtils.createJwt(claims);
        // 利用uuid当做键,将token存储到redis
        redisUtil.setCacheObject("user:key:"+uuid,token,expireTime, TimeUnit.SECONDS);

        return token;
    }

    @Override
    public User selectByUsername(String username) {
        return userMapper.selectByUsername(username);
    }


    @Override
    public List<UserVO> list(UserDTO userDTO) {
        List<UserVO> list = userMapper.list(userDTO);
        System.out.println("list = " + list);
        return list;
    }

    @Override
    public void delete(int id) {
        userMapper.delete(id);
    }


    @Override
    public void deleteAll(List<Integer> ids) {
        userMapper.deleteAll(ids);
    }


    //输入参数为UserVO,然后向tb_user表进行添加向sys_user_role表进行添加,向sys_role进行添加rolename
    @Transactional
    @Override
    public void add(UserVO userVO) {
        // 1. 插入用户基本信息到tb_user
        User user = new User();
        BeanUtils.copyProperties(userVO, user);
        user.setCreateTime(new Date());
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        user.setPassword(encoder.encode(user.getPassword()));
        userMapper.add(user);
        Integer userId = user.getId();


        //获取角色信息
        String roleName = userVO.getRoleName();
        //根据名字添加角色,返回id
        int roleId = roleMapper.addByRoleName(roleName);
        //根据两个id进行添加
        sysUserRoleMapper.addByUserIdAndRoleId(userId,roleId);

    }


    @Override
    public int update(UserVO uservo) {
        //修改时间为当前时间
        Date date = new Date();
        uservo.setCreateTime(date);
        //创建密码加密器对象
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encode = encoder.encode(uservo.getPassword());
        uservo.setPassword(encode);
        return userMapper.update(uservo);
    }



    @Override
    public List<RolePermission> selectPermission() {
        return userMapper.selectPermission();

    }
}
